/**
 * PANDA 3D SOFTWARE
 * Copyright (c) Carnegie Mellon University.  All rights reserved.
 *
 * All use of this software is subject to the terms of the revised BSD
 * license.  You should have received a copy of this license along
 * with this source code in a file named "LICENSE."
 *
 * @file dcTypedef.cxx
 * @author drose
 * @date 2004-06-17
 */

#include "dcTypedef.h"
#include "dcParameter.h"
#include "dcSimpleParameter.h"
#include "dcindent.h"

using std::string;

/**
 * The DCTypedef object becomes the owner of the supplied parameter pointer
 * and will delete it upon destruction.
 */
DCTypedef::
DCTypedef(DCParameter *parameter, bool implicit) :
  _parameter(parameter),
  _bogus_typedef(false),
  _implicit_typedef(implicit),
  _number(-1)
{
}

/**
 * Creates a bogus typedef reference.
 */
DCTypedef::
DCTypedef(const string &name) :
  _parameter(new DCSimpleParameter(ST_invalid)),
  _bogus_typedef(true),
  _implicit_typedef(false),
  _number(-1)
{
  _parameter->set_name(name);
}

/**
 *
 */
DCTypedef::
~DCTypedef() {
  delete _parameter;
}

/**
 * Returns a unique index number associated with this typedef definition.
 * This is defined implicitly when the .dc file(s) are read.
 */
int DCTypedef::
get_number() const {
  return _number;
}

/**
 * Returns the name of this typedef.
 */
const string &DCTypedef::
get_name() const {
  return _parameter->get_name();
}

/**
 * Returns a brief decription of the typedef, useful for human consumption.
 */
string DCTypedef::
get_description() const {
  std::ostringstream strm;
  _parameter->output(strm, true);
  return strm.str();
}

/**
 * Returns true if the typedef has been flagged as a bogus typedef.  This is
 * set for typedefs that are generated by the parser as placeholder for
 * missing typedefs, as when reading a partial file; it should not occur in a
 * normal valid dc file.
 */
bool DCTypedef::
is_bogus_typedef() const {
  return _bogus_typedef;
}

/**
 * Returns true if the typedef has been flagged as an implicit typedef,
 * meaning it was created for a DCClass that was referenced inline as a type.
 */
bool DCTypedef::
is_implicit_typedef() const {
  return _implicit_typedef;
}

/**
 * Returns a newly-allocated DCParameter object that uses the same type as
 * that named by the typedef.
 */
DCParameter *DCTypedef::
make_new_parameter() const {
  DCParameter *new_parameter = _parameter->make_copy();
  new_parameter->set_name(string());
  new_parameter->set_typedef(this);
  return new_parameter;
}

/**
 * Assigns the unique number to this typedef.  This is normally called only by
 * the DCFile interface as the typedef is added.
 */
void DCTypedef::
set_number(int number) {
  _number = number;
}

/**
 * Write a string representation of this instance to <out>.
 */
void DCTypedef::
output(std::ostream &out, bool brief) const {
  out << "typedef ";
  _parameter->output(out, false);
}

/**
 *
 */
void DCTypedef::
write(std::ostream &out, bool brief, int indent_level) const {
  indent(out, indent_level)
    << "typedef ";

  // We need to preserve the parameter name in the typedef (this is the
  // typedef name); hence, we pass brief = false to output().
  _parameter->output(out, false);
  out << ";";

  if (!brief) {
    out << "  // typedef " << _number;
  }
  out << "\n";
}
